package cn.t.facade.order;


import cn.t.constants.CommonConstants;
import cn.t.constants.ParamConstants;
import cn.t.constants.ResponseError;
import cn.t.converter.order.OrderDTOConverter;
import cn.t.converter.order.OrderModelConverter;
import cn.t.converter.order.WorkOrderDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.core.facade.FacadeImpl;
import cn.t.core.mode.PageInfoDTO;
import cn.t.core.mode.PageQueryDTO;
import cn.t.core.mode.YesNoEnum;
import cn.t.dto.api.CustomerItemDTO;
import cn.t.dto.device.vo.OpenCloseDTO;
import cn.t.dto.order.CreateOrderRequest;
import cn.t.dto.order.DislodgeOrderDTO;
import cn.t.dto.order.OrderDTO;
import cn.t.dto.order.OrderDetailDTO;
import cn.t.dto.order.OrderQueryRequest;
import cn.t.dto.order.UpdateOrderDTO;
import cn.t.dto.order.base.OrderSnRequest;
import cn.t.dto.order.base.VBaseDTO;
import cn.t.dto.order.excelresp.DislodgeExcelResp;
import cn.t.dto.sku.SkuDTO;
import cn.t.enums.order.ErrorTypeEnum;
import cn.t.enums.order.MsvmOrderStatusEnum;
import cn.t.enums.order.OrderTransferStatusEnum;
import cn.t.enums.order.OrderTypeEnum;
import cn.t.enums.order.WorkStatusEnum;
import cn.t.facade.user.CostCenterFacade;
import cn.t.model.device.DeviceDO;
import cn.t.model.order.ExceptionLogDO;
import cn.t.model.order.OrderDO;
import cn.t.model.order.OrderDetailDO;
import cn.t.model.order.WorkOrderDO;
import cn.t.model.user.CostCenterDO;
import cn.t.service.device.DeviceService;
import cn.t.service.order.ExceptionLogService;
import cn.t.service.order.OrderDetailService;
import cn.t.service.order.OrderService;
import cn.t.service.order.WorkOrderDetailService;
import cn.t.service.order.WorkOrderService;
import cn.t.service.sku.SkuService;
import cn.t.service.user.UserQueryService;
import cn.t.utils.MsvmUtil;
import cn.t.vo.order.DislodgeOrderDetailVO;
import cn.t.vo.order.UpdateOrderGoodsVO;
import cn.t.vo.user.ParticipantWithUserVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 领料订单表(Order)服务编排
 *
 * @author t
 * @since 2024-05-24 10:19:34
 */
@Slf4j
@Service
@AllArgsConstructor
public class OrderFacade extends FacadeImpl<OrderDTO, OrderDO, OrderDTOConverter, OrderService> {
    /**
     * 手动创建领料单
     *
     * @param request 参数
     */
    @Transactional
    public String createOrder(CreateOrderRequest request) {

        Long deviceId = request.getDeviceId();
        //校验设备信息
        DeviceDO deviceDO = deviceService.findById(deviceId);
        if (ObjectUtils.isEmpty(deviceDO)) {
            throw new BizException(ResponseError.DEVICE_NOT_FOUND, String.format(ResponseError.DEVICE_NOT_FOUND.getName(), deviceId.toString()));
        }
        ParticipantWithUserVO userQueryDO = userQueryService.findMaterIssuerByFirmCard(deviceDO.getFirmId(), request.getCardCode());
        if (ObjectUtils.isNotEmpty(userQueryDO)) {
            String orderSn = MsvmUtil.getBdOrderSn(request.getDeviceId());
            //创建领料订单信息
            OrderDTO orderDTO = OrderModelConverter.convertVoToOrderDto(request, deviceDO, userQueryDO);
            orderDTO.setOrderSn(orderSn);
            OrderDO orderDO = converter.dto2Model(orderDTO);
            //创建系统工单
            String workOrderSn = workOrderFacade.addWorkOrderByOrder(orderDO);
            orderDetailFacade.saveOrUpdate(request.getOrderGoodsList(), orderDO);
            orderDO.setWorkOrderSn(workOrderSn);
            //创建领料订单信息
            service.add(orderDO);
            return orderSn;
        } else {
            throw new BizException(ResponseError.USER_NOT_FOUND, String.format(ResponseError.USER_NOT_FOUND.getName(), request.getCardCode()));

        }
    }

    /**
     * 整单删除
     */
    @Transactional
    public void deleteOrder(String orderSn) {
        OrderDO orderDO = service.getOrderDO(orderSn);
        orderDO.setIsDeleted(YesNoEnum.TRUE);
        Boolean o = service.removeOrderById(orderDO.getId());
        //更新用户
        Boolean og = orderDetailFacade.deleteOrderDetail(orderSn, null);
        Boolean flag = (o && og) == Boolean.TRUE ? Boolean.TRUE : Boolean.FALSE;
        if (flag) {
            workOrderFacade.removeByWorkOrderSn(orderSn);
            return;
        }

        throw new BizException(ResponseError.ORDER_DELETE_FAILED, String.format(ResponseError.ORDER_DELETE_FAILED.getName(), orderSn));
    }


    @Transactional
    public void updateOrderGoods(UpdateOrderDTO request) {
        //查询订单信息
        String orderSn = request.getOrderSn();
        OrderDO orderDO = service.getOrderDO(orderSn);

        //校验设备信息
        DeviceDO deviceDO = deviceService.findById(orderDO.getDeviceId());
        if (ObjectUtils.isEmpty(deviceDO)){
            throw new BizException(ResponseError.DEVICE_NOT_FOUND, String.format(ResponseError.DEVICE_NOT_FOUND.getName(), orderDO.getDeviceId().toString()));
        }

        OrderDetailDTO orderDetailDO = new OrderDetailDTO();
        orderDetailDO.setOrderSn(orderSn);
        List<OrderDetailDTO> orderGoods = orderDetailFacade.queryList(orderDetailDO, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);

        if (ObjectUtils.isEmpty(orderGoods)){
            throw new BizException(ResponseError.ORDER_GOODS_NOT_FOUND, ResponseError.ORDER_GOODS_NOT_FOUND.getCode());
        }

        Map<Long, OrderDetailDTO> orderGoodsDoMap = orderGoods.stream().collect(Collectors.toMap(OrderDetailDTO::getId, Function.identity()));
        List<UpdateOrderGoodsVO> orderGoodsList = request.getOrderGoodsList();
        //筛选出更新id不为空的VO.需要修改的数据
        List<Long> orderGoodsIds = orderGoodsList.stream().
                map(UpdateOrderGoodsVO::getSid).distinct().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());

        //筛选出需要删除的数据
        List<OrderDetailDTO> orderGoodsListDel = orderGoods.stream().filter(orderGoodsDO -> !orderGoodsIds.contains(orderGoodsDO.getId())).collect(Collectors.toList());

        //筛选出需要更新的数据
        List<UpdateOrderGoodsVO> orderGoodsListUpdate = orderGoodsList.stream()
                .filter(orderGoodsDO -> orderGoodsDoMap.containsKey(orderGoodsDO.getSid())).collect(Collectors.toList());

        //更新行信息
        Boolean listUpdate = updateGoodsInfo(orderGoodsListUpdate, orderDO);

        //新增行信息
        List<UpdateOrderGoodsVO> orderGoodsListAdd = orderGoodsList.stream().
                filter(updateOrderGoodsReq -> ObjectUtils.isEmpty(updateOrderGoodsReq.getSid()) || updateOrderGoodsReq.getSid() == 0).collect(Collectors.toList());
        Boolean listAdd = addOrderGoods(orderGoodsListAdd, orderDO);


        //删除行信息
        Boolean listDel = delGoodsInfo(orderGoodsListDel, orderSn);


        //创建系统工单
        workOrderFacade.removeByWorkOrderSn(orderDO.getWorkOrderSn());
        String workOrderSn = workOrderFacade.addWorkOrderByOrder(orderDO);
        orderDO.setWorkOrderSn(workOrderSn);
        service.update(orderDO);

        boolean flag = listDel && listUpdate && listAdd;
        if (!flag) {
            throw new BizException(ResponseError.ORDER_UPDATE_FAILED, ResponseError.ORDER_UPDATE_FAILED.getName());
        }

    }

    public Boolean addOrderGoods(List<UpdateOrderGoodsVO> orderGoods, OrderDO orderDO) {
        if (CollectionUtils.isEmpty(orderGoods)) {
            return Boolean.TRUE;
        }
        return orderDetailFacade.saveOrUpdate(orderGoods, orderDO);
    }

    public Boolean delGoodsInfo(List<OrderDetailDTO> orderGoods, String orderSn) {
        List<Long> ids = orderGoods.stream().map(OrderDetailDTO::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderGoods)) {
            return Boolean.TRUE;
        }
        return orderDetailFacade.deleteOrderDetail(orderSn, ids);
    }

    public Boolean updateGoodsInfo(List<UpdateOrderGoodsVO> orderGoods, OrderDO orderDO) {
        if (CollectionUtils.isEmpty(orderGoods)) {
            return Boolean.TRUE;
        }
        return orderDetailFacade.saveOrUpdate(orderGoods, orderDO);
    }

    //获取订单分页列表
    public PageInfoDTO<DislodgeOrderDTO> getUnclaimedList(PageQueryDTO<OrderQueryRequest> requestPageQuery, OrderTypeEnum orderType) {
        requestPageQuery.getParam().setExceptionType(ErrorTypeEnum.ERROR10.getCode());
        List<OrderDO> list = service.getErrList(requestPageQuery);
        //数据处理
        return new PageInfoDTO<>(requestPageQuery.getPageNo(), requestPageQuery.getPageSize(), service.queryErrOrderCount(requestPageQuery.getParam()), commonOrderFacade.getList(list, orderType));
    }

    public PageInfoDTO<DislodgeOrderDTO> getOrderListPage(PageQueryDTO<OrderQueryRequest> requestPageQuery, OrderTypeEnum orderType) {
        List<OrderDO> list = service.getList(requestPageQuery, orderType);
        //数据处理
        return new PageInfoDTO<>(requestPageQuery.getPageNo(), requestPageQuery.getPageSize(), service.queryOrderCount(requestPageQuery.getParam(), orderType), commonOrderFacade.getList(list, orderType));
    }
    public OrderDO getOrderDO(String orderSn) {
        return service.getOrderDO(orderSn);
    }
    //获取订单详情
    public VBaseDTO<DislodgeOrderDTO, DislodgeOrderDetailVO> getDislodgeInfo(OrderSnRequest param, OrderTypeEnum orderType) {
        VBaseDTO<DislodgeOrderDTO, DislodgeOrderDetailVO> vBaseDTO = new VBaseDTO<>();
        String orderSn = param.getOrderSn();
        vBaseDTO.setDataMain(commonOrderFacade.getDislodgeOrderDTO(orderSn));

        //行信息查询，（异常订单查询未处理的）
        OrderDetailDO orderDetailDTO = new OrderDetailDO();
        orderDetailDTO.setOrderSn(orderSn);
        if (OrderTypeEnum.ERRORDER_TYPE.equals(orderType)) {
            orderDetailDTO.setOrderTransferStatus(OrderTransferStatusEnum.NOTRANSFER.getCode());
        }
        List<DislodgeOrderDetailVO> dislodgeOrderDetail = orderDetailFacade.getDislodgeOrderDetail(orderDetailDTO);
        //异常信息查询
        Map<Integer, ExceptionLogDO> exceptionLogMap = new HashMap<>();
        if (Arrays.asList(OrderTypeEnum.ERRORDER_TYPE, OrderTypeEnum.UN_ORDER).contains(orderType)) {
            exceptionLogMap = exceptionLogService.queryListByNo(Collections.singletonList(orderSn)).stream().collect(Collectors.toMap(ExceptionLogDO::getCargowayNo, Function.identity(), (q1, q2) -> q2));
        }

        //数据处理
  /*      Map<Integer, ExceptionLogDO> finalExceptionLogMap = exceptionLogMap;
        dislodgeOrderDetail.forEach(dislodgeOrderDetailVO -> {
            ExceptionLogDO exceptionLogDO = finalExceptionLogMap.get(dislodgeOrderDetailVO.getCargowayNo());
            if (exceptionLogDO != null) {
                dislodgeOrderDetailVO.setExceptionTypeName(ErrorTypeEnum.getDescByKey(exceptionLogDO.getExceptionType()));
                dislodgeOrderDetailVO.setOrderTransferStatusName(
                        OrderTransferStatusEnum.getDescByKey(exceptionLogDO.getOrderTransferStatus()));
            }
        });*/
        vBaseDTO.setDetail(dislodgeOrderDetail);
        return vBaseDTO;
    }


    // 查询订单

    public List<DislodgeExcelResp> openRecordExcel(OrderQueryRequest param) {

        List<OrderDO> list =setPageList(param, OrderTypeEnum.ORDER);
        //数据处理
        if (ObjectUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<String> orderSnList = list.stream().map(OrderDO::getOrderSn).collect(Collectors.toList());
        List<Long> costCenterIds = list.stream().map(OrderDO::getCostCenterId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
        //行数据数据分页处理
        OrderDetailDO orderDetailDO = new OrderDetailDO();
        orderDetailDO.setOrderSnList(orderSnList);
        List<OrderDetailDO> orderDetails = commonOrderFacade.exportPageList(orderDetailDO);

        Map<String, DislodgeOrderDTO> orderMap = commonOrderFacade.getList(list, OrderTypeEnum.ORDER).stream().collect(Collectors.toMap(DislodgeOrderDTO::getOrderSn, Function.identity()));
        Map<Long, CostCenterDO> costCenterList = costCenterFacade.getCostCenterList(costCenterIds);
        //数据封装
        List<DislodgeExcelResp> dislodgeExcelResps = orderDetails.stream().map(dislodgeOrder -> {
            DislodgeOrderDTO orderDTO = orderMap.get(dislodgeOrder.getOrderSn());

            DislodgeExcelResp dislodgeExcelResp = OrderModelConverter.convertExcelDetail(dislodgeOrder, orderDTO);
            if (ObjectUtils.isNotEmpty(orderDTO.getCostCenterId())) {
                CostCenterDO costCenterDO = costCenterList.get(orderDTO.getCostCenterId());
                dislodgeExcelResp.setCostCenterCode(costCenterDO == null ? "" : costCenterDO.getCostCenterCode());
            }

            return dislodgeExcelResp;
        }).collect(Collectors.toList());
        //赋值客户物料号
        return setCustomerItemDTO(dislodgeExcelResps);

    }


    public List<OrderDO> setPageList(OrderQueryRequest param, OrderTypeEnum orderType) {
        List<OrderDO> allOrders = new ArrayList<>();
        int pageSize = ParamConstants.PAGE_MAX_SIZE;
        int pageNo = ParamConstants.INT_1;
        // 设置最大记录数限制
        int maxRecords = ParamConstants.EXPORTPAGEMAXSIZE;
        // 记录已查询到的总记录数
        int totalRecords = 0;
        PageQueryDTO<OrderQueryRequest> requestPageQuery = new PageQueryDTO<>();
        while (totalRecords < maxRecords) {
            requestPageQuery.setParam(param);
            requestPageQuery.setPageNo(pageNo);
            requestPageQuery.setPageSize(pageSize);

            List<OrderDO> orders = service.getList(requestPageQuery,orderType);
            if (orders.isEmpty()) {
                break; // 如果没有更多数据，退出循环
            }

            // 计算可以添加的订单数量
            allOrders.addAll(orders);
            totalRecords+= orders.size();

            if (totalRecords >= maxRecords) {
                break; // 如果已达到最大记录数，退出循环
            }

            pageNo++;
        }
        return allOrders;
    }

    public List<DislodgeExcelResp> setCustomerItemDTO(List<DislodgeExcelResp> list) {
        Map<String, List<DislodgeExcelResp>> collect = list.stream().collect(Collectors.groupingBy(DislodgeExcelResp::getCustomerCode));

        return collect.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
    }

    @Transactional
    public OrderDO addOrder(OpenCloseDTO openCloseDO, List<OrderDetailDO> orderDetailDOList) {
        OrderDO orderDO1 = new OrderDO();
        orderDO1.setOrderSn(openCloseDO.getOrderSn());
        OrderDO orderDO = service.findInfoByModel(orderDO1);
        if (!org.springframework.util.ObjectUtils.isEmpty(orderDO)) {
            //非第一次关门门
            log.warn("非第一次开门 {}", openCloseDO.getOrderSn());
            OrderDetailDO template = new OrderDetailDO();
            template.setOrderSn(openCloseDO.getOrderSn());
            orderDetailService.deleteOrderDetail(template, new ArrayList<>());
        } else {
            orderDO = converter.setOderDo(openCloseDO);

        }
        if (orderDO.getOrderStatus() == null) {
            //异常
            boolean isErr = openCloseDO.getQtyList().stream().anyMatch(qtyVO -> qtyVO.getErrorTypeEnum() != null) || openCloseDO.getErrorTypeEnum() != null;
            if (isErr || org.springframework.util.ObjectUtils.isEmpty(openCloseDO.getQtyList())) {
                orderDO.setOrderStatus(MsvmOrderStatusEnum.ERR_ORDER.getCode());
            } else {
                orderDO.setOrderStatus(MsvmOrderStatusEnum.NORMAL.getCode());
            }
        }

        Long id = orderDO.getId();
        String operatorInfo = openCloseDO.getOperatorInfo();
        if (orderDO.getId() != null) {
            orderDO.setModifier(operatorInfo);
            service.update(orderDO);
        } else {
            orderDO.setCreator(operatorInfo);
            orderDO.setModifier(operatorInfo);
            id = service.addAndReturnId(orderDO);
            orderDO.setId(id);
        }
        if (!org.springframework.util.ObjectUtils.isEmpty(orderDetailDOList)) {
            orderDetailDOList.forEach(orderDetailDO -> {
                orderDetailDO.setModifier(operatorInfo);
                orderDetailDO.setCreator(operatorInfo);
            });
            orderDetailService.saveOrUpdateBatch(orderDetailDOList);
        }
        return orderDO;
    }

    @Transactional
    public OrderDO  addStartInfo(OpenCloseDTO openCloseWeightVO, Map<String, SkuDTO> skuMap) {
        // 获取工单号
        String workOrderSn = this.workOrderService.getWorkOrderSn(CommonConstants.WORK_START_DEFAULT_SY);
        //生成领用订单
        OrderDO orderDO = addOrder(openCloseWeightVO, new ArrayList<>());

        if (openCloseWeightVO.getWorkOrderSn()==null){
            WorkOrderDO workOrderDO = new WorkOrderDO();
            workOrderDO.setEmpNo(openCloseWeightVO.getEmployeeCode());
            workOrderDO.setWorkOrderSn(workOrderSn);
            workOrderDO.setStatus(WorkStatusEnum.WAIT_DO.getCode());
            //生成工单
            workOrderDTOConverter.data2Do(orderDO, workOrderDO);
            workOrderService.add(workOrderDO);
            //生成工单明细
            workOrderDetailService.addDetailList(openCloseWeightVO.getQtyList(), skuMap, workOrderDO);
            //更新工单号
            orderDO.setWorkOrderSn(workOrderSn);
            update(converter.model2Dto(orderDO));
        }
return orderDO;

    }

    @Resource
    private WorkOrderService workOrderService;
    @Resource
    protected WorkOrderDTOConverter workOrderDTOConverter;
    @Resource
    private WorkOrderDetailService workOrderDetailService;
    @Resource
    private DeviceService deviceService;
    @Resource
    private CommonOrderFacade commonOrderFacade;
    @Resource
    private CostCenterFacade costCenterFacade;
    @Resource
    private OrderDetailFacade orderDetailFacade;
    @Resource
    private ExceptionLogService exceptionLogService;
    @Resource
    private WorkOrderFacade workOrderFacade;

    @Resource
    private UserQueryService userQueryService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private SkuService skuService;



}

